package com.levi.juc.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * ABA问题
 * A把值改成1,又把1改回来了，但是B是不知情的，以为还是原来的值，其实这个值已经被动过了,已经不是原来的数据
 * 原子引用，   本质上使用乐观锁解决，每个操作都加一个版本号
 *
 */
public class AtomicRefrenceTest {
    public static void main(String[] args) {
        //期望的初始值，和初始时间戳，初始时间戳相当于是一个版本号
        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1, 1);

        /**
         * A线程先把变量的值改为2，然后又改回来，版本号其实增加了2，变成了3
         */
        new Thread(()->{

//            int stamp = atomicStampedReference.getStamp();
//            System.out.println("a1>>>="+stamp);
//            try {
//                TimeUnit.SECONDS.sleep(2);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            atomicStampedReference.compareAndSet(1,  //期待的值
                    2,                                   //要修改成的值
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1);
            System.out.println("a2>>="+atomicStampedReference.getStamp());//  时间戳为2

            atomicStampedReference.compareAndSet(2,
                    1,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1);
            System.out.println("a3>>="+atomicStampedReference.getStamp());//时间戳为3
        },"A").start();


        int stamp = atomicStampedReference.getStamp();
        System.out.println("b1>>>="+stamp);
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /**
         * B线程以为还是原来的1，版本号也是1，其实不是，所以返回false，修改失败
         */
        new Thread(()->{

            System.out.println(atomicStampedReference.compareAndSet(1,
                    11,
                    1,
                    atomicStampedReference.getStamp() + 1));
        },"B").start();

    }
}
